package com.pine.dbant.core.plugin;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.pine.dbant.common.plugin.*;
import com.pine.sunflower.core.LifeCycledAdapter;
import com.pine.sunflower.core.utils.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author xiaoyuan
 * @create 2022/11/17 15:26
 **/
@Component
@Slf4j
public class DefaultPluginFactory extends LifeCycledAdapter implements PluginFactory {

    private static final Table<String, String, PluginMeta> PLUGIN_META_TABLE = HashBasedTable.create();

    private static final Map<String, Plugin> PLUGIN_TABLE = new HashMap<>();

    @Override
    public void registerPlugin(Plugin plugin) {
        com.pine.dbant.common.plugin.annotion.Plugin pluginAnnotion = plugin.getClass().getAnnotation(com.pine.dbant.common.plugin.annotion.Plugin.class);
        if (pluginAnnotion == null) {
            throw new PluginException(Strings.format("该类未添加插件注解@Plugin。className={}", plugin.getClass().getName()));
        }
        String id = pluginAnnotion.id().toLowerCase(Locale.ROOT);
        if (PLUGIN_TABLE.containsKey(id)) {
            throw new PluginException(Strings.format("插件[{}]已存在，请保证插件id不冲突", pluginAnnotion.id()));
        }
        PluginMeta pluginMeta = new PluginMeta(pluginAnnotion.type(), id, StringUtils.isNotBlank(pluginAnnotion.label())?
                pluginAnnotion.label():pluginAnnotion.id());
        pluginMeta.setJavascriptFilename(pluginAnnotion.javascriptFilename());
        PLUGIN_META_TABLE.put(pluginMeta.getPluginType().name(), id, pluginMeta);
        PLUGIN_TABLE.put(id, plugin);
        log.debug("插件[{}]已安装",pluginAnnotion.id());
    }

    @Override
    public Plugin getPlugin(String name) {
        return PLUGIN_TABLE.get(name.toLowerCase(Locale.ROOT));
    }

    @Override
    public PluginMeta getPluginMeta(String name) {
        return PLUGIN_META_TABLE.values().stream().filter(pluginMeta -> pluginMeta.getId().equalsIgnoreCase(name)).findAny().orElse(null);
    }

    @Override
    public List<PluginMeta> getPlugins(PluginType pluginType) {
        return new ArrayList<>(PLUGIN_META_TABLE.row(pluginType.name()).values());
    }
}
